package com.study.easyexcel.business.template;

import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.study.easyexcel.common.exception.CheckedException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 特殊组数据（平面组模板{@link FlatGroupTemplate}）的样式填充处理器
 *
 * @author yuhuan
 * @date 2023/12/26
 */
public abstract class BaseFlatGroupStyleHandler extends UniversalGroupStyle {

    /**
     * 标题行，以及对应的列索引，索引从0开始，多个列逗号拼接，-1表示全列
     */
    protected HashMap<Integer, String> titleRowColMap;

    /**
     * 合计行，以及对应的列索引，索引从0开始，多个列逗号拼接，-1表示全列
     * 注意：该映射应该与{@link #titleRowColMap}成对存在，这样才能让{@link #currentTitleRowIndex(Integer)}确认准确的标题行
     */
    protected HashMap<Integer, String> totalRowColMap;

    @Override
    public int order() {
        return 50002;
    }

    /**
     * Tip：如果出现部分的列没有进入该方法，请检查填充那一列的占位符是否正确；占位符对应列没有数据或没有添加空数据会导致该列被忽略
     */
    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        Cell cell = context.getCell();
        int rowIndex = cell.getRowIndex();
        // 标题行样式
        if (checkRowColMap(titleRowColMap, rowIndex)) {
            setCellStyle(context, cell, titleRowColMap, this::setTitleCellStyle);
        }
        // 合计行样式
        if (checkRowColMap(totalRowColMap, rowIndex)) {
            setCellStyle(context, cell, totalRowColMap, this::setTotalCellStyle);
        }
    }

    /**
     * 添加标题行的单元格样式。子类重写可以选择不走统一样式，如果需要则需手动调用{@link #createCellUnifiedStyle(Workbook, int)}，
     * 否则统一样式不会生效
     */
    protected abstract void setTitleCellStyle(CellWriteHandlerContext context, Cell cell);

    /**
     * 添加合计行的单元格样式。
     *
     * @see #setTitleCellStyle(CellWriteHandlerContext, Cell)
     */
    protected abstract void setTotalCellStyle(CellWriteHandlerContext context, Cell cell);

    /**
     * 获取当前合计组的标题行索引
     *
     * @param totalRowIndex 当前合计行索引
     * @return 当前数据组的标题行索引
     */
    protected Integer currentTitleRowIndex(Integer totalRowIndex) {
        if (this.titleRowColMap.size() != this.totalRowColMap.size()) {
            throw new CheckedException("检查到标题行与合计行不是成对存在，无法从标题行中确认准确的索引。");
        }
        // 所有标题行的索引
        Set<Integer> keys = titleRowColMap.keySet();
        // 所有小于当前合计行索引的标题行索引
        List<Integer> tempList = keys.stream().filter(k -> k < totalRowIndex).collect(Collectors.toList());
        // 最接近当前合计行索引的标题行索引
        return Collections.min(tempList, Comparator.comparingInt(a -> Math.abs(a - totalRowIndex)));
    }
}
